{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "rZrqLsMVLzhH"
   },
   "source": [
    "# Form Parsing using Google Cloud Document AI\n",
    "\n",
    "This notebook shows how to use Google Cloud Document AI to parse a campaign disclosure form.\n",
    "\n",
    "It accompanies this Medium article:\n",
    "https://medium.com/@lakshmanok/how-to-parse-forms-using-google-cloud-document-ai-68ad47e1c0ed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!sudo chown -R jupyter:jupyter /home/jupyter/training-data-analyst/blogs/form_parser/formparsing.ipynb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 72
    },
    "id": "nCYVjxP_L0-3",
    "outputId": "5c0e129c-4495-46bb-fe34-8102ca9d3d58"
   },
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "\n",
       "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
       "  <td>\n",
       "    <a target=\"_blank\" href=\"https://console.cloud.google.com/ai-platform/notebooks/deploy-notebook?name=Form+Parsing+Using+Google+Cloud+Document+AI&url=https%3A%2F%2Fgithub.com%2FGoogleCloudPlatform%2Ftraining-data-analyst%2Fblob%2Fmaster%2Fblogs%2Fform_parser%2Fformparsing.ipynb&download_url=https%3A%2F%2Fgithub.com%2FGoogleCloudPlatform%2Ftraining-data-analyst%2Fraw%2Fmaster%2Fblogs%2Fform_parser%2Fformparsing.ipynb\">\n",
       "    <img src=\"https://raw.githubusercontent.com/GoogleCloudPlatform/practical-ml-vision-book/master/logo-cloud.png\"/> Run in AI Platform Notebook</a>\n",
       "  </td>\n",
       "  </td>\n",
       "  <td>\n",
       "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/GoogleCloudPlatform/training-data-analyst/blob/master/blogs/form_parser/formparsing.ipynb\">\n",
       "    <img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Run in Google Colab</a>\n",
       "  </td>\n",
       "  <td>\n",
       "    <a target=\"_blank\" href=\"https://github.com/GoogleCloudPlatform/training-data-analyst/blob/master/blogs/form_parser/formparsing.ipynb\">\n",
       "    <img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />View source on GitHub</a>\n",
       "  </td>\n",
       "  <td>\n",
       "    <a href=\"https://raw.githubusercontent.com/GoogleCloudPlatform/training-data-analyst/master/blogs/form_parser/formparsing.ipynb\">\n",
       "    <img src=\"https://www.tensorflow.org/images/download_logo_32px.png\" />Download notebook</a>\n",
       "  </td>\n",
       "</table>\n"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import Markdown as md\n",
    "\n",
    "### change to reflect your notebook\n",
    "_nb_repo = 'training-data-analyst'\n",
    "_nb_loc = \"blogs/form_parser/formparsing.ipynb\"\n",
    "_nb_title = \"Form Parsing Using Google Cloud Document AI\"\n",
    "\n",
    "### no need to change any of this\n",
    "_nb_safeloc = _nb_loc.replace('/', '%2F')\n",
    "_nb_safetitle = _nb_title.replace(' ', '+')\n",
    "md(\"\"\"\n",
    "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://console.cloud.google.com/ai-platform/notebooks/deploy-notebook?name={1}&url=https%3A%2F%2Fgithub.com%2FGoogleCloudPlatform%2F{3}%2Fblob%2Fmaster%2F{2}&download_url=https%3A%2F%2Fgithub.com%2FGoogleCloudPlatform%2F{3}%2Fraw%2Fmaster%2F{2}\">\n",
    "    <img src=\"https://raw.githubusercontent.com/GoogleCloudPlatform/practical-ml-vision-book/master/logo-cloud.png\"/> Run in AI Platform Notebook</a>\n",
    "  </td>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/GoogleCloudPlatform/{3}/blob/master/{0}\">\n",
    "    <img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Run in Google Colab</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://github.com/GoogleCloudPlatform/{3}/blob/master/{0}\">\n",
    "    <img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />View source on GitHub</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a href=\"https://raw.githubusercontent.com/GoogleCloudPlatform/{3}/master/{0}\">\n",
    "    <img src=\"https://www.tensorflow.org/images/download_logo_32px.png\" />Download notebook</a>\n",
    "  </td>\n",
    "</table>\n",
    "\"\"\".format(_nb_loc, _nb_safetitle, _nb_safeloc, _nb_repo))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "C3Lth94lLzhH"
   },
   "source": [
    "### Document\n",
    "\n",
    "As an example, let's take this US election campaign disclosure form."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash\n",
    "if [ ! -f scott_walker.pdf ]; then\n",
    "   curl -O https://storage.googleapis.com/practical-ml-vision-book/images/scott_walker.pdf\n",
    "fi"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "id": "JFX0yhI9LzhH",
    "outputId": "bb1a77d4-8d5d-4d6f-a586-89aec45e10ab"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "scott_walker.pdf\n"
     ]
    }
   ],
   "source": [
    "!ls *.pdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "id": "d-lTZleFLzhI",
    "outputId": "c5c035b4-46c5-4799-af4b-beb284044b87"
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "        <iframe\n",
       "            width=\"600\"\n",
       "            height=\"300\"\n",
       "            src=\"./scott_walker.pdf\"\n",
       "            frameborder=\"0\"\n",
       "            allowfullscreen\n",
       "        ></iframe>\n",
       "        "
      ],
      "text/plain": [
       "<IPython.lib.display.IFrame at 0x7fd1b17056d0>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import IFrame\n",
    "IFrame(\"./scott_walker.pdf\", width=600, height=300)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Note**: If the file is not visible, simply open the PDF file by double-clicking on it in the left hand menu."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "fEmyXAKqLzhI"
   },
   "source": [
    "## Upload to Cloud Storage\n",
    "\n",
    "Document AI works with documents on Cloud Storage, so let's upload the doc."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "pELR6oRjLzhI"
   },
   "outputs": [],
   "source": [
    "BUCKET=\"ai-analytics-solutions-kfpdemo\"  # CHANGE to a bucket that you own"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "OdazYmCNLzhI",
    "outputId": "a4077cb2-2674-4a59-cedf-64712ccd66c3"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Copying file://scott_walker.pdf [Content-Type=application/pdf]...\n",
      "/ [1 files][209.7 KiB/209.7 KiB]                                                \n",
      "Operation completed over 1 objects/209.7 KiB.                                    \n"
     ]
    }
   ],
   "source": [
    "!gcloud storage cp scott_walker.pdf gs://{BUCKET}/formparsing/scott_walker.pdf"   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "POuMjyuaLzhI",
    "outputId": "742c6bed-c389-4f04-e75b-62e8006d89d7"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "gs://ai-analytics-solutions-kfpdemo/formparsing/scott_walker.pdf\n"
     ]
    }
   ],
   "source": [
    "!gcloud storage ls gs://{BUCKET}/formparsing/scott_walker.pdf"   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "y1cYougzLzhJ"
   },
   "source": [
    "## Enable Document AI\n",
    "\n",
    "1. First enable Document AI in your project by visiting\n",
    "https://console.developers.google.com/apis/api/documentai.googleapis.com/overview\n",
    "\n",
    "2. Find out who you are running as:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "8irAEgGMLzhJ",
    "outputId": "50b39add-6b11-47af-f1b8-8ad4a7d8dc70"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                  Credentialed Accounts\n",
      "ACTIVE  ACCOUNT\n",
      "*       379218021631-compute@developer.gserviceaccount.com\n",
      "\n",
      "To set the active account, run:\n",
      "    $ gcloud config set account `ACCOUNT`\n",
      "\n"
     ]
    }
   ],
   "source": [
    "!gcloud auth list"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "dv7mSzJmLzhJ"
   },
   "source": [
    "3. Create a service account authorization by visiting\n",
    "https://console.cloud.google.com/iam-admin/serviceaccounts/create\n",
    "Give this service account Document AI Core Service Account authorization\n",
    "\n",
    "4. Give the above ACTIVE ACCOUNT the ability to use the service account you just created."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "YVEKdZu5LzhJ"
   },
   "source": [
    "## Call Document AI"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "qkStGkajLzhJ",
    "outputId": "bb35174f-d206-4fd9-a309-e9e3bf9d5005"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sending the following request to Document AI in ai-analytics-solutions (us region), saving to response.json\n",
      "{\n",
      "   \"inputConfig\":{\n",
      "      \"gcsSource\":{\n",
      "         \"uri\":\"gs://ai-analytics-solutions-kfpdemo/formparsing/scott_walker.pdf\"\n",
      "      },\n",
      "      \"mimeType\":\"application/pdf\"\n",
      "   },\n",
      "   \"documentType\":\"general\",\n",
      "   \"formExtractionParams\":{\n",
      "      \"enabled\":true\n",
      "   }\n",
      "}\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current\n",
      "                                 Dload  Upload   Total   Spent    Left  Speed\n",
      "100 3366k    0 3366k  100   246   832k     60  0:00:04  0:00:04 --:--:--  832k\n"
     ]
    }
   ],
   "source": [
    "%%bash\n",
    "PDF=\"gs://ai-analytics-solutions-kfpdemo/formparsing/scott_walker.pdf\" # CHANGE to your PDF file\n",
    "REGION=\"us\"  # change to EU if the bucket is in the EU\n",
    "\n",
    "cat <<EOM > request.json\n",
    "{\n",
    "   \"inputConfig\":{\n",
    "      \"gcsSource\":{\n",
    "         \"uri\":\"${PDF}\"\n",
    "      },\n",
    "      \"mimeType\":\"application/pdf\"\n",
    "   },\n",
    "   \"documentType\":\"general\",\n",
    "   \"formExtractionParams\":{\n",
    "      \"enabled\":true\n",
    "   }\n",
    "}\n",
    "EOM\n",
    "\n",
    "# Send request to Document AI.\n",
    "PROJECT=$(gcloud config get-value project)\n",
    "echo \"Sending the following request to Document AI in ${PROJECT} ($REGION region), saving to response.json\"\n",
    "cat request.json\n",
    "\n",
    "curl -X POST \\\n",
    "  -H \"Authorization: Bearer \"$(gcloud auth application-default print-access-token) \\\n",
    "  -H \"Content-Type: application/json; charset=utf-8\" \\\n",
    "  -d @request.json \\\n",
    "  https://${REGION}-documentai.googleapis.com/v1beta2/projects/${PROJECT}/locations/us/documents:process \\\n",
    "  > response.json"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "bznl9nKQLzhJ",
    "outputId": "ae04505c-29b9-4659-d9f1-5878e4ac5768"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                }\n",
      "              ]\n",
      "            },\n",
      "            \"orientation\": \"PAGE_UP\"\n",
      "          }\n",
      "        }\n",
      "      ]\n",
      "    }\n",
      "  ]\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "!tail response.json"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Note**: If you get a 403 PERMISSION DENIED error, please wait a minute and re-run the previous two cells. If it persists, re-run all the cells from the top."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "BLp8X9KmLzhJ"
   },
   "source": [
    "## Parse the response\n",
    "\n",
    "Let's use Python to parse the response and pull out specific fields.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "LISGX0yXLzhJ"
   },
   "outputs": [],
   "source": [
    "import json\n",
    "ifp = open('response.json')\n",
    "response = json.load(ifp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "nHGFFF7yLzhJ",
    "outputId": "92014cf5-ab24-4533-96b8-ddce3936bc1d"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10/09/2020 15:51\n",
      "Image# 202010099285076251\n",
      "PAGE 1/14\n",
      "7\n",
      "REPORT OF RECEIPTSFECAND DISBURSEMENTSFORM 3P\n"
     ]
    }
   ],
   "source": [
    "allText = response['text']\n",
    "print(allText[:100])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "MLdh-asbLzhJ"
   },
   "source": [
    "### Option 1: Parsing blocks of text\n",
    "\n",
    "As an example, let's try to get the \"Cash on Hand\". This is in Page 2 and the answer is $75,931.36\n",
    "All the data in the document is the allText field. we just need to find the right starting and ending index\n",
    "for what we want to extract."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "skhK81fZLzhJ",
    "outputId": "1ea207de-b5a3-4d51-c912-3b665d33e66b"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1719\n"
     ]
    }
   ],
   "source": [
    "print(allText.index(\"CASH ON HAND\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "HQk_TjuNLzhJ"
   },
   "source": [
    "We know that \"Cash on Hand\" is on Page 2."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "OncXL_BmLzhJ",
    "outputId": "eb0eef30-0ee3-47a2-c91d-689aa247fb49"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'layout': {'textAnchor': {'textSegments': [{'startIndex': '1716',\n",
       "     'endIndex': '1827'}]},\n",
       "  'confidence': 1,\n",
       "  'boundingPoly': {'normalizedVertices': [{'x': 0.068627454, 'y': 0.24873738},\n",
       "    {'x': 0.6764706, 'y': 0.24873738},\n",
       "    {'x': 0.6764706, 'y': 0.25757575},\n",
       "    {'x': 0.068627454, 'y': 0.25757575}]},\n",
       "  'orientation': 'PAGE_UP'}}"
      ]
     },
     "execution_count": 33,
     "metadata": {
      "tags": []
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "response['pages'][1]['blocks'][21]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "SVvXLzO3LzhJ",
    "outputId": "2cba7ef7-d0c1-4fc9-a1de-d770d9a2f571"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'startIndex': '1716', 'endIndex': '1827'}"
      ]
     },
     "execution_count": 34,
     "metadata": {
      "tags": []
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "response['pages'][1]['blocks'][21]['layout']['textAnchor']['textSegments'][0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "q_7xy4OSLzhJ",
    "outputId": "22622468-1938-4308-92d2-d3c2ecf46b33"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'6. CASH ON HAND AT BEGINNING OF REPORTING PERIOD .............................................................\\n'"
      ]
     },
     "execution_count": 35,
     "metadata": {
      "tags": []
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "startIndex = int(response['pages'][1]['blocks'][21]['layout']['textAnchor']['textSegments'][0]['startIndex'])\n",
    "endIndex = int(response['pages'][1]['blocks'][21]['layout']['textAnchor']['textSegments'][0]['endIndex'])\n",
    "allText[startIndex:endIndex]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Zk9u8S1xLzhJ"
   },
   "source": [
    "Cool, we are at the right part of the document! Let's get the next block, which should be the actual amount."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "fQj_yEdgLzhJ",
    "outputId": "0f4642af-9ed4-4106-9542-6a1752800958"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "75931.36\n"
     ]
    }
   ],
   "source": [
    "def extractText(allText, layoutIdx, elem):\n",
    "    startIndex = int(elem['textAnchor']['textSegments'][layoutIdx]['startIndex'])\n",
    "    endIndex = int(elem['textAnchor']['textSegments'][layoutIdx]['endIndex'])\n",
    "    return allText[startIndex:endIndex].strip()\n",
    "\n",
    "amount = float(extractText(allText, 0, response['pages'][1]['blocks'][22]['layout']))\n",
    "print(amount)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "T_ZtWSltLzhJ"
   },
   "source": [
    "### Option 2: Parsing form fields\n",
    "\n",
    "What we did with blocks of text was quite low-level. Document AI understands that forms tend to have key-value pairs, and part of the JSON response includes these extracted key-value pairs as well.\n",
    "\n",
    "Besides FormField Document AI also supports getting Paragraph and Table from the document."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "dUBw0AVELzhJ",
    "outputId": "e6f5f063-c651-41d1-b405-e2a1fe3c7d81"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict_keys(['pageNumber', 'dimension', 'layout', 'blocks', 'paragraphs', 'lines', 'tokens', 'tables', 'formFields'])"
      ]
     },
     "execution_count": 47,
     "metadata": {
      "tags": []
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "response['pages'][1].keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "5UUDghY6LzhJ",
    "outputId": "e0784ef0-961a-47a8-9f91-7f47c88c8f9b"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'fieldName': {'textAnchor': {'textSegments': [{'startIndex': '1719',\n",
       "     'endIndex': '1765'}]},\n",
       "  'confidence': 0.9962783,\n",
       "  'boundingPoly': {'normalizedVertices': [{'x': 0.0922335, 'y': 0.24873738},\n",
       "    {'x': 0.4584429, 'y': 0.24873738},\n",
       "    {'x': 0.4584429, 'y': 0.2587827},\n",
       "    {'x': 0.0922335, 'y': 0.2587827}]},\n",
       "  'orientation': 'PAGE_UP'},\n",
       " 'fieldValue': {'textAnchor': {'textSegments': [{'startIndex': '1716',\n",
       "     'endIndex': '1842'}]},\n",
       "  'confidence': 0.9962783,\n",
       "  'boundingPoly': {'normalizedVertices': [{'x': 0.068627454, 'y': 0.24873738},\n",
       "    {'x': 0.90849674, 'y': 0.24873738},\n",
       "    {'x': 0.90849674, 'y': 0.26767677},\n",
       "    {'x': 0.068627454, 'y': 0.26767677}]},\n",
       "  'orientation': 'PAGE_UP'}}"
      ]
     },
     "execution_count": 51,
     "metadata": {
      "tags": []
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "response['pages'][1]['formFields'][2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "fPd2nYE0LzhK",
    "outputId": "bf66982a-a849-4c04-d832-59d30fd487ba"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "key=CASH ON HAND AT BEGINNING OF REPORTING PERIOD\n",
      "value=6. CASH ON HAND AT BEGINNING OF REPORTING PERIOD .............................................................\n",
      "75931.36\n",
      ", , .\n"
     ]
    }
   ],
   "source": [
    "fieldName = extractText(allText, 0, response['pages'][1]['formFields'][2]['fieldName'])\n",
    "fieldValue = extractText(allText, 1, response['pages'][1]['formFields'][2]['fieldValue'])\n",
    "print('key={}\\nvalue={}'.format(fieldName, fieldValue))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "7QRKvF9NLzhK"
   },
   "source": [
    "Enjoy!\n",
    "\n",
    "Copyright 2021 Google Inc. Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [],
   "name": "formparsing.ipynb",
   "provenance": []
  },
  "environment": {
   "name": "tf2-gpu.2-1.m59",
   "type": "gcloud",
   "uri": "gcr.io/deeplearning-platform-release/tf2-gpu.2-1:m59"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
